using System;
using Unity.Burst;

namespace UnityEngine.Animations.Rigging
{
    [DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Mirror Constraint")]
    [HelpURL("")]
    public class MirrorConstraint : RigConstraint<
        MirrorConstraintJob,
        MirrorConstraintData,
        MirrorConstraintJobBinder>
    {
#if UNITY_EDITOR
#pragma warning disable 0414
        [NotKeyable, SerializeField, HideInInspector] private bool m_SourceObjectsGUIToggle;
        [NotKeyable, SerializeField, HideInInspector] private bool m_SettingsGUIToggle;
#endif
    }

    [BurstCompile]
    public struct MirrorConstraintJob : IWeightedAnimationJob
    {
        public ReadWriteTransformHandle constrained;
        public ReadOnlyTransformHandle source;

        public FloatProperty jobWeight { get; set; }

        public void ProcessAnimation(AnimationStream stream)
        {
            Debug.Log("MirrorConstraintJob::ProcessAnimation");
            float weight = jobWeight.Get(stream);
            if (weight > 0f)
            {
                constrained.SetLocalPosition(
                        stream,
                        //math.lerp(constrained.GetPosition(stream), source.GetPosition(stream), weight)
                        -1f * source.GetLocalPosition(stream)
                    );
            }
        }

        public void ProcessRootMotion(AnimationStream stream)
        {
            Debug.Log("MirrorConstraintJob::ProcessRootMotion");
        }
    }

    [Serializable]
    public struct MirrorConstraintData : IAnimationJobData
    {
        public Transform constrainedObject;
        [SyncSceneToStream] public Transform sourceObject;

        public bool IsValid()
        {
            return !(constrainedObject == null || sourceObject == null);
        }

        public void SetDefaultValues()
        {
            constrainedObject = null;
            sourceObject = null;
        }
    }

    public class MirrorConstraintJobBinder : AnimationJobBinder<
        MirrorConstraintJob,
        MirrorConstraintData>
    {
        public override MirrorConstraintJob Create(Animator animator, ref MirrorConstraintData data, Component component)
        {
            Debug.Log("MirrorConstraintJobBinder::Create");
            return new MirrorConstraintJob()
            {
                constrained = ReadWriteTransformHandle.Bind(animator, data.constrainedObject),
                source = ReadOnlyTransformHandle.Bind(animator, data.sourceObject)
            };
        }

        public override void Destroy(MirrorConstraintJob job)
        {
            Debug.Log("MirrorConstraintJobBinder::Destroy");
        }
    }
}